package com.atldy.redis.service.impl;

import com.atldy.redis.pojo.dto.UserAddDTO;
import com.atldy.redis.pojo.vo.UserVO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atldy.redis.pojo.User;
import com.atldy.redis.service.UserService;
import com.atldy.redis.mapper.UserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * <h2>  </h2>
 *
 * @author: li-dong-yang
 * @CreateTime: 2021/11/1 11:11
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    public static final String USER_KEY = "USER:";

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addUser(UserAddDTO dto) {
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        user.setCreateTime(new Date());
        boolean flag = this.save(user);
        //新增成功缓存到redis
        if (flag) {
            Optional.ofNullable(this.getById(user.getId())).ifPresent(user1 -> {
                redisTemplate.opsForValue().set(USER_KEY + user1.getId(), user1);
            });
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deletedUser(Integer id) {
        //逻辑删除，进行修改操作
        String key = USER_KEY + id;
        //先删除数据库，再删除redis
        boolean flag = this.removeById(id);
        if (flag) {
            //    在查询是否删除，物理删除不用查询
            User user = this.getById(id);
            if (user == null) {
                redisTemplate.delete(key);
            }
        }
        return flag;
    }

    @Override
    public Boolean updateUser(UserAddDTO dto) {
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        user.setCreateTime(new Date());
        boolean flag = this.updateById(user);
        //更新成功缓存到redis
        if (flag) {
            Optional.ofNullable(this.getById(user.getId())).ifPresent(user1 -> {
                redisTemplate.opsForValue().set(USER_KEY + user1.getId(), user1);
            });
        }
        return flag;
    }

    @Override
    public UserVO getUserById(Integer id) {
        String key = USER_KEY + id;
        //先从redis中获取
        UserVO vo = new UserVO();
        User user = (User) redisTemplate.opsForValue().get(key);
        if (user == null) {
            //    redis里面没有查询MySQL
            user = this.getById(id);
            if (user == null) {
                return vo;
            } else {
                redisTemplate.opsForValue().set(key, user);
            }
        }
        BeanUtils.copyProperties(user, vo);
        return vo;
    }

    /**
     * <p>防止缓存击穿</p>
     *
     * @date: 2021-11-09 22:25
     * @param: [id]
     */
    public UserVO getUserById1(Integer id) {
        String key = USER_KEY + id;
        //先从redis中获取
        UserVO vo = new UserVO();
        User user = (User) redisTemplate.opsForValue().get(key);
        if (user == null) {
            //枷锁保证一次只能有一个请求进来，防止大量请求查询MySQL，造成数据库崩溃
            synchronized (UserServiceImpl.class) {
                // 查询MySQL
                user = this.getById(id);
                //如果查询还是为null,直接返回
                if (user == null) {
                    return null;
                }
                //    不为null，缓存redis,设置过期时间
                redisTemplate.opsForValue().setIfAbsent(key, user, 100, TimeUnit.SECONDS);
            }
        }
        BeanUtils.copyProperties(user, vo);
        return vo;
    }

}




